import { useAppStore } from '@/stores/app'
import dayjs from 'dayjs'
import { decode } from 'js-base64'
import { type DetailedError, Upload } from 'tus-js-client'
export type uploadConf = {
  endpoint: string
  file: File
  chunkSize: number
  afterSuccess: (...args: any[]) => void
}
export default function useUpload() {
  const appStore = useAppStore()
  const percentage = ref<number>(0)
  const tus = ref<Upload>()
  const currentUploadFile = ref()
  const uploadError = ref<boolean>(false)
  const resolving = ref(false)
  function initTus(uploadConf: uploadConf) {
    tus.value = new Upload(uploadConf.file, {
      endpoint: uploadConf.endpoint,
      chunkSize: uploadConf.chunkSize,
      onShouldRetry: () => {
        return false
      },
      headers: {
        authorization: 'Bearer ' + appStore.token
      },
      metadata: {
        filename: uploadConf.file.name,
        filetype: uploadConf.file.type
      },
      onError: async (error) => {
        const result = (await tus.value?.findPreviousUploads()) ?? []
        currentUploadFile.value = result?.find(
          (item) =>
            item.metadata.filename === tus.value?.options.metadata?.filename
        )
        const status = (
          (error as DetailedError)?.originalResponse?.getStatus() ?? 500
        ).toString()
        const serverError =
          (error as DetailedError)?.originalResponse?.getBody() ?? ''
        const xError =
          (error as DetailedError)?.originalResponse?.getHeader(
            'X-Tus-Error'
          ) ?? ''
        let errorText = '上传失败，请重新上传'
        if (status.startsWith('5') && serverError) {
          errorText = serverError
        }
        if (xError.length > 0) {
          const text = encodeURIComponent(xError)
          errorText = decode(text)
        }
        handleError(currentUploadFile.value?.urlStorageKey, errorText)
      },
      onSuccess() {
        percentage.value = 100
        const data = tus.value?.url
        uploadConf.afterSuccess(data)
        //ToastUtils.success('上传成功')
        tus.value?.options.urlStorage?.removeUpload(
          currentUploadFile.value?.urlStorageKey
        )
      },
      onChunkComplete(_chunk, bytesAccepted, bytesTotal) {
        const number = Number(((bytesAccepted / bytesTotal) * 100).toFixed(2))
        if (number < 100) {
          percentage.value = number
        }
      },
      onAfterResponse: async (req) => {
        const result = (await tus.value?.findPreviousUploads()) ?? []
        currentUploadFile.value = result?.find(
          (item) =>
            item.metadata.filename === tus.value?.options.metadata?.filename
        )
        if (req.getMethod() === 'PATCH') {
          const accepts = req.getHeader('Upload-Offset')
          const lastChunk =
            Number(accepts) + uploadConf.chunkSize * 2 >= uploadConf.file.size // 这里表示倒数第二片已完成
          if (lastChunk) {
            // 最后一片开始上传时进入解析状态
            //resolving.value = true
          }
        }
      }
    })
  }
  function handleError(
    currentFileKey?: string
    //error: string = '上传失败，请重新上传'
  ) {
    resolving.value = false
    uploadError.value = true
    percentage.value = 0
    //ToastUtils.error(error)
    currentFileKey &&
      tus.value?.options.urlStorage?.removeUpload(currentFileKey)
  }
  function pauseUpload() {
    tus.value?.abort()
  }
  function continueUpload() {
    startOrResumeUpload()
  }

  function askToResumeUpload(previousUploads: any[]) {
    if (previousUploads.length === 0) return null
    const result = previousUploads
      .map((item) => {
        const createTime = item.creationTime
        const now = Date.now()
        const timeDiff = dayjs(now).diff(createTime, 'hour')
        const key = item.urlStorageKey
        if (timeDiff > 0) {
          // 上传时间超过1天未进行续传则重新上传
          tus.value?.options.urlStorage?.removeUpload(key)
          return null
        }
        return item
      })
      .filter(Boolean)
    if (result.length === 0) return null
    return result[0]
  }
  function startOrResumeUpload() {
    tus.value?.findPreviousUploads().then(function (previousUploads) {
      const chosenUpload = askToResumeUpload(previousUploads)
      if (chosenUpload) {
        tus.value?.resumeFromPreviousUpload(chosenUpload)
      }
      tus.value?.start()
      uploadError.value = false // 开始上传关闭错误状态
    })
  }
  return {
    percentage,
    uploadError,
    resolving,
    initTus,
    startOrResumeUpload,
    pauseUpload,
    continueUpload
  }
}
